#include "UeventListener.h"
#include <sys/socket.h>
#include<string.h>
#include <unistd.h> 
#include <linux/netlink.h> 
#include <linux/rtnetlink.h>
#include <net/if.h> 
#include <iostream> 

void UeventListener::startListening() {
    if (m_running) {
        std::cerr << "已经在监听中，不需要重新启动" << std::endl;
        return;
    }
    m_running = true;

    //创建 netlink socket为m_netlinkFd
    int m_netlinkFd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 
    if (m_netlinkFd < 0) {
        std::cerr << "创建NETLINK_ROUTE套接字失败: " << strerror(errno) << std::endl;
        return;
    }
    
    //绑定到RTMGRP_LINK组播组
    struct sockaddr_nl addr;
    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_pid = getpid();

    // 设置要监听的组,可以加上RTMGRP_IPV4_IFADDR: 监听IPv4地址变化。RTMGRP_IPV4_ROUTE: 监听IPv4路由变化
    addr.nl_groups = RTMGRP_LINK;

    // 绑定套接字
    if (bind(m_netlinkFd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        std::cerr << "绑定NETLINK_ROUTE套接字失败: " << strerror(errno) << std::endl;
        close(m_netlinkFd);
        return;
    }

    // 设置接收缓冲区大小
    int rcvbuf = 1024 * 1024; // 1MB
    // 设置套接字接收缓冲区大小三
    if (setsockopt(m_netlinkFd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) < 0) {
        std::cerr << "设置套接字接收缓冲区失败: " << strerror(errno) << std::endl;
    }


    // 启动监听线程
    m_listenerThread = std::thread(&UeventListener::listenerLoop, this);
    std::cout << "网络接口状态监听器已启动" << std::endl;
}

void UeventListener::stopListening() {
    if (!m_running) 
        return;
    m_running = false;
    if (m_netlinkFd >= 0) {
        close(m_netlinkFd);
        m_netlinkFd = -1;
    }
    if (m_listenerThread.joinable()) {
        m_listenerThread.join();
    }
}


void UeventListener::addCallback(NetworkEventCallback* callback) {
    std::lock_guard<std::mutex> lock(m_callbackMutex);
    m_callbacks.push_back(callback);
}

void UeventListener::removeCallback(NetworkEventCallback* callback) {
    std::lock_guard<std::mutex> lock(m_callbackMutex);
    for (auto it = m_callbacks.begin(); it != m_callbacks.end(); ) {
        if (*it == callback) {
            it = m_callbacks.erase(it);
        } else {
            ++it;
        }
    }
}

void UeventListener::listenerLoop() 
{
    fds[0].fd = m_netlinkFd; //需要监听的文件描述符
    fds[0].events = POLLIN; //监听可读事件
    int ret = poll(fds, 1, -1);
    if (ret < 0) {
        if (errno == EINTR) {
            continue; // 重启poll
        }
        std::cerr << "[UeventListener] poll error: " << strerror(errno) << std::endl;
        break;
    }
    if (ret == 0) {
        // 超时(若不是-1), 继续循环
        continue;
    }

    while (m_running) {
        struct pollfd fds[1];//fds数组，容量为1,里面的数据类型为struct pollfd。

        if (fds[0].revents & POLLIN) {
            char buf[4096];
            memset(buf, 0, sizeof(buf));
            int nbytes = recv(m_netlinkFd, buf, sizeof(buf), 0);//接收的字节数
            if (nbytes < 0) {
                if (errno == EAGAIN || errno == EINTR) continue;
                std::cerr << "[UeventListener] recv error: "
                          << strerror(errno) << std::endl;
                break;
            }
            //解析 netlink 消息
            parseRawEventData(buf);
        }
    }
    std::cerr << "[UeventListener] 网络接口状态监听线程已终止\n";
}

NetworkEvent UeventListener::parseRawEventData(const char* buf, int len) {
    const struct nlmsghdr* nlh = (const struct nlmsghdr*)buf;

    //遍历所有消息
    for (; NLMSG_OK(nlh, (unsigned)len); nlh = NLMSG_NEXT(nlh, len)){
        //处理接口信息消息
        if (nlh->nlmsg_type == RTM_NEWLINK || nlh->nlmsg_type == RTM_DELLINK) 
        {
            const struct ifinfomsg* ifi = reinterpret_cast<const struct ifinfomsg*>(NLMSG_DATA(nlh));
            // 获取接口名称
            char ifname[IF_NAMESIZE];
            if_indextoname(ifi->ifi_index, ifname);

            // 确定接口状态
            bool isUp = (ifi->ifi_flags & IFF_UP) && (ifi->ifi_flags & IFF_RUNNING);
            std::string status = isUp ? "UP" : "DOWN";

            // 创建网络事件
            std::string eventType = isUp ? "INTERFACE_UP" : "INTERFACE_DOWN";
            std::string additionalInfo = "Interface: " + std::string(ifname) + 
                                        ", Status: " + status + 
                                        ", Index: " + std::to_string(ifi->ifi_index);
            
            NetworkEvent event(eventType, ifname, additionalInfo);
    
            // 分发
            notifyAll(event);
        }
    }
}


void UeventListener::notifyAll(const NetworkEvent& event) {
    std::lock_guard<std::mutex> lock(m_callbackMutex);
    for (auto* cb : m_callbacks) {
        if (cb) {
            cb->onNetworkEvent(event);
        }
    }
}
